home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 4
/
Aminet 4 - November 1994.iso
/
aminet
/
util
/
gnu
/
gnuplot_3_5.lha
/
gnuplot
/
os2gclient.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-09-16
|
37KB
|
1,106 lines
#ifdef INCRCSDATA
static char RCSid[]="$Id: gclient.c%v 3.50 1993/07/09 05:35:24 woo Exp $" ;
#endif
/****************************************************************************
PROGRAM: Gnupmdrv
MODULE: gclient.c
This file contains the client window procedures for Gnupmdrv
****************************************************************************/
/*
* PM driver for GNUPLOT
* Copyright (C) 1992 Roger Fearick
*
* Permission to use, copy, and distribute this software and its
* documentation for any purpose with or without fee is hereby granted,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation.
*
* Permission to modify the software is granted, but not the right to
* distribute the modified code. Modifications are to be distributed
* as patches to released version.
*
* This software is provided "as is" without express or implied warranty.
*
*
* AUTHOR
*
* Gnuplot driver for OS/2: Roger Fearick
*
* Send your comments or suggestions to
* info-gnuplot@dartmouth.edu.
* This is a mailing list; to join it send a note to
* info-gnuplot-request@dartmouth.edu.
* Send bug reports to
* bug-gnuplot@dartmouth.edu.
**/
#define INCL_PM
#define INCL_WIN
#define INCL_SPL
#define INCL_SPLDOSPRINT
#define INCL_WINSTDFONT
#define INCL_DOSMEMMGR
#define INCL_DOSPROCESS
#define INCL_DOSERRORS
#define INCL_DOSFILEMGR
#define INCL_DOSNMPIPES
#define INCL_DOSSESMGR
#define INCL_DOSSEMAPHORES
#define INCL_DOSMISC
#define INCL_DOSQUEUES
#define INCL_WINSWITCHLIST
#include <os2.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <process.h>
#include "gnupmdrv.h"
/*==== g l o b a l d a t a ================================================*/
extern char szIPCName[] ; /* name used in IPC with gnuplot */
/*==== l o c a l d a t a ==================================================*/
#define GNUBUF 1024 /* buffer for gnuplot commands */
#define PIPEBUF 4096 /* size of pipe buffers */
#define CMDALLOC 4096 /* command buffer allocation increment (ints) */
#define ENVSIZE 2048 /* size of environment */
#define GNUPAGE 4096 /* size of gnuplot page in pixels (driver dependent) */
#define PAUSE_DLG 1 /* pause handled in dialog box */
#define PAUSE_BTN 2 /* pause handled by menu item */
#define PAUSE_GNU 3 /* pause handled by Gnuplot */
static HWND hWndstart ; /* used for errors in startup */
static ULONG pidGnu=0L ; /* gnuplot session id */
static ULONG ppidGnu=0L ; /* gnuplot pid */
static HPS hpsScreen ; /* screen pres. space */
static HSWITCH hSwitch = 0 ; /* switching between windows */
static SWCNTRL swGnu ;
static BOOL bLineTypes = FALSE ;
static BOOL bLineThick = FALSE ;
static BOOL bColours = TRUE ;
static BOOL bShellPos = FALSE ;
static BOOL bPlotPos = FALSE ;
static ULONG ulPlotPos[4] ;
static ULONG ulShellPos[4] ;
static char szFontNameSize[FONTBUF] ;
static char achPrinterName[128] = "" ;
static PRQINFO3 infPrinter = { "" } ;
static HMTX semCommands ;
static HEV semStartSeq ; /* semaphore to start things in right sequence */
static HEV semPause ;
static ULONG ulPauseReply = 1 ;
static ULONG ulPauseMode = PAUSE_DLG ;
/* commands from gnuplot come via this ... */
static HPIPE hRead = 0L ;
/* stuff for screen-draw thread control */
static BOOL bExist ;
static BOOL bStopDraw ;
static HEV semDrawDone ;
static HEV semStartDraw ;
/* command buffer */
static int ncalloc = 0 ;
static int ic = 0 ;
static volatile int *commands = NULL ;
/*==== f u n c t i o n s =====================================================*/
int DoPrint( HWND ) ;
MRESULT WmClientCmdProc( HWND , ULONG, MPARAM, MPARAM ) ;
void ChangeCheck( HWND, USHORT, USHORT ) ;
BOOL QueryIni( HAB ) ;
static void SaveIni( void ) ;
static void ThreadDraw( void ) ;
static void DoPaint( HWND, HPS ) ;
static void Display( void ) ;
void SelectFont( HPS, char *, short );
static void ReadGnu( void ) ;
static void WaitEnd( void ) ;
static void AllocMore() ;
static int BufRead( HFILE, void*, int, PULONG ) ;
int GetNewFont( HWND, HPS ) ;
/*==== c o d e ===============================================================*/
MRESULT EXPENTRY DisplayClientWndProc(HWND hWnd, ULONG message, MPARAM mp1, MPARAM mp2)
/*
** Window proc for main window
** -- passes most stuff to active child window via WmClientCmdProc
** -- passes DDE messages to DDEProc
*/
{
HDC hdcScreen ;
SIZEL sizlPage ;
TID tidDraw, tidSpawn ;
char *pp ;
ULONG ulID ;
ULONG ulFlag ;
char szErrs[128] ;
switch (message) {
case WM_CREATE:
// set initial values
ChangeCheck( hWnd, IDM_LINES_THICK, bLineThick?IDM_LINES_THICK:0 ) ;
ChangeCheck( hWnd, IDM_LINES_SOLID, bLineTypes?0:IDM_LINES_SOLID ) ;
ChangeCheck( hWnd, IDM_COLOURS, bColours?IDM_COLOURS:0 ) ;
hWndstart = hWnd ; /* used in ReadGnu for errors */
// disable close from system menu (close only from gnuplot)
WinSendMsg( WinWindowFromID( WinQueryWindow( hWnd, QW_PARENT ), FID_SYSMENU ),
MM_SETITEMATTR,
MPFROM2SHORT(SC_CLOSE, TRUE ),
MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED ) ) ;
// setup semaphores
DosCreateMutexSem( NULL, &semCommands, 0L, 0L ) ;
DosCreateEventSem( NULL, &semStartDraw, 0L, 0L ) ;
DosCreateEventSem( NULL, &semDrawDone, 0L, 0L ) ;
DosCreateEventSem( NULL, &semStartSeq, 0L, 0L ) ;
DosCreateEventSem( NULL, &semPause, 0L, 0L ) ;
bStopDraw = FALSE ;
bExist = TRUE ;
// create a dc and hps to draw on the screen
hdcScreen = WinOpenWindowDC( hWnd ) ;
sizlPage.cx = GNUPAGE ; sizlPage.cy = GNUPAGE ;
hpsScreen = GpiCreatePS( hab, hdcScreen, &sizlPage,
PU_ARBITRARY|GPIT_MICRO|GPIA_ASSOC) ;
// spawn a thread to do the drawing
DosCreateThread( &tidDraw, (PFNTHREAD)ThreadDraw, 0L, 0L, 8192L ) ;
// then spawn server for GNUPLOT ...
DosCreateThread( &tidSpawn, (PFNTHREAD)ReadGnu, 0L, 0L, 8192L ) ;
DosWaitEventSem( semStartSeq, SEM_INDEFINITE_WAIT ) ;
// get details of command-line window
hSwitch = WinQuerySwitchHandle( 0, ppidGnu ) ;
WinQuerySwitchEntry( hSwitch, &swGnu ) ;
// set size of this window
WinSetWindowPos( WinQueryWindow( hWnd, QW_PARENT ),
HWND_TOP,
ulShellPos[0],
ulShellPos[1],
ulShellPos[2],
ulShellPos[3],
bShellPos?SWP_SIZE|SWP_MOVE|SWP_SHOW|SWP_ACTIVATE:SWP_SHOW|SWP_ACTIVATE ) ;
// clear screen
DosPostEventSem( semDrawDone ) ;
break ;
case WM_COMMAND:
return WmClientCmdProc( hWnd , message , mp1 , mp2 ) ;
case WM_CLOSE:
if( WinSendMsg( hWnd, WM_USER_PRINT_QBUSY, 0L, 0L ) != 0L ) {
WinMessageBox( HWND_DESKTOP,
hWnd,
"Still printing - not closed",
APP_NAME,
0,
MB_OK | MB_ICONEXCLAMATION ) ;
return 0L ;
}
return (WinDefWindowProc(hWnd, message, mp1, mp2));
case WM_PAINT:
DoPaint( hWnd, hpsScreen ) ;
break ;
case WM_SIZE :
WinInvalidateRect( hWnd, NULL, TRUE ) ;
break ;
case WM_PRESPARAMCHANGED:
pp = malloc(FONTBUF) ;
if( WinQueryPresParam( hWnd,
PP_FONTNAMESIZE,
0,
&ulID,
FONTBUF,
pp,
QPF_NOINHERIT ) != 0L ) {
strcpy( szFontNameSize, pp ) ;
WinInvalidateRect( hWnd, NULL, TRUE ) ;
}
free(pp) ;
break ;
case WM_USER_PRINT_BEGIN:
case WM_USER_PRINT_OK :
case WM_USER_DEV_ERROR :
case WM_USER_PRINT_ERROR :
case WM_USER_PRINT_QBUSY :
return( PrintCmdProc( hWnd, message, mp1, mp2 ) ) ;
case WM_GNUPLOT:
// display the plot
WinSetWindowPos( hwndFrame, HWND_TOP, 0,0,0,0, SWP_ACTIVATE|SWP_ZORDER ) ;
WinInvalidateRect( hWnd, NULL, TRUE ) ;
return 0L ;
case WM_PAUSEPLOT:
/* put pause message on screen, or enable 'continue' button */
if( ulPauseMode == PAUSE_DLG ) {
WinLoadDlg( HWND_DESKTOP,
hWnd,
(PFNWP)PauseMsgDlgProc,
0L,
IDD_PAUSEBOX,
(char*)mp1 ) ;
}
else {
WinEnableMenuItem( WinWindowFromID(
WinQueryWindow( hWnd, QW_PARENT ), FID_MENU ),
IDM_CONTINUE,
TRUE ) ;
}
return 0L ;
case WM_PAUSEEND:
/* resume plotting */
ulPauseReply = (ULONG) mp1 ;
DosPostEventSem( semPause ) ;
return 0L ;
default: /* Passes it on if unproccessed */
return (WinDefWindowProc(hWnd, message, mp1, mp2));
}
return (NULL);
}
MRESULT WmClientCmdProc(HWND hWnd, ULONG message, MPARAM mp1, MPARAM mp2)
/*
** Handle client window command (menu) messages
** -- mostly passed on to active child window
**
*/
{
ULONG usDlg ;
extern HWND hApp ;
static ulPauseItem = IDM_PAUSEDLG ;
switch( (USHORT) SHORT1FROMMP( mp1 ) ) {
case IDM_ABOUT : /* show the 'About' box */
WinDlgBox( HWND_DESKTOP,
hWnd ,
(PFNWP)About ,
0L,
ID_ABOUT,
NULL ) ;
break ;
case IDM_PRINT : /* print plot */
if( SetupPrinter( hWnd, achPrinterName, &infPrinter ) )
WinPostMsg( hWnd, WM_USER_PRINT_BEGIN, (MPARAM)&infPrinter, 0L ) ;
break ;
case IDM_PRINTSETUP : /* select printer */
WinDlgBox( HWND_DESKTOP,
hWnd ,
(PFNWP)QPrintersDlgProc,
0L,
IDD_QUERYPRINT,
achPrinterName ) ;
break ;
case IDM_LINES_THICK:
// change line setting
bLineThick = !bLineThick ;
ChangeCheck( hWnd, IDM_LINES_THICK, bLineThick?IDM_LINES_THICK:0 ) ;
WinInvalidateRect( hWnd, NULL, TRUE ) ;
break ;
case IDM_LINES_SOLID:
// change line setting
bLineTypes = !bLineTypes ;
ChangeCheck( hWnd, IDM_LINES_SOLID, bLineTypes?0:IDM_LINES_SOLID ) ;
WinInvalidateRect( hWnd, NULL, TRUE ) ;
break ;
case IDM_COLOURS:
// change colour setting
bColours = !bColours ;
ChangeCheck( hWnd, IDM_COLOURS, bColours?IDM_COLOURS:0 ) ;
WinInvalidateRect( hWnd, NULL, TRUE ) ;
break ;
case IDM_FONTS:
if( GetNewFont( hWnd, hpsScreen ) )
WinInvalidateRect( hWnd, NULL, TRUE ) ;
break ;
case IDM_SAVE :
SaveIni() ;
break ;
case IDM_COMMAND: /* go back to GNUPLOT command window */
WinSwitchToProgram( hSwitch ) ;
break ;
case IDM_CONTINUE:
WinPostMsg( hWnd, WM_PAUSEEND, 1L, 0L ) ;
WinEnableMenuItem( WinWindowFromID(
WinQueryWindow( hWnd, QW_PARENT ), FID_MENU ),
IDM_CONTINUE,
FALSE ) ;
break ;
case IDM_PAUSEGNU: /* gnuplot handles pause */
ChangeCheck( hWnd, ulPauseItem, IDM_PAUSEGNU ) ;
ulPauseItem = IDM_PAUSEGNU ;
ulPauseMode = PAUSE_GNU ;
break ;
case IDM_PAUSEDLG: /* pause message in dlg box */
ChangeCheck( hWnd, ulPauseItem, IDM_PAUSEDLG ) ;
ulPauseItem = IDM_PAUSEDLG ;
ulPauseMode = PAUSE_DLG ;
break ;
case IDM_PAUSEBTN: /* pause uses menu button, no message */
ChangeCheck( hWnd, ulPauseItem, IDM_PAUSEBTN ) ;
ulPauseItem = IDM_PAUSEBTN ;
ulPauseMode = PAUSE_BTN ;
break ;
case IDM_HELPFORHELP:
WinSendMsg(WinQueryHelpInstance(hWnd),
HM_DISPLAY_HELP, 0L, 0L ) ;
return 0L ;
case IDM_EXTENDEDHELP:
WinSendMsg(WinQueryHelpInstance(hWnd),
HM_EXT_HELP, 0L, 0L);
return 0L ;
case IDM_KEYSHELP:
WinSendMsg(WinQueryHelpInstance(hWnd),
HM_KEYS_HELP, 0L, 0L);
return 0L ;
case IDM_HELPINDEX:
WinSendMsg(WinQueryHelpInstance(hWnd),
HM_HELP_INDEX, 0L, 0L);
return 0L ;
default :
return WinDefWindowProc( hWnd, message, mp1, mp2 ) ;
}
return( NULL ) ;
}
void ChangeCheck( HWND hWnd , USHORT wItem1 , USHORT wItem2 )
/*
** Utility function:
**
** move check mark from menu item 1 to item 2
*/
{
HWND hMenu ;
hMenu = WinWindowFromID( WinQueryWindow( hWnd, QW_PARENT ),
FID_MENU ) ;
if( wItem1 != 0 )
WinSendMsg( hMenu,
MM_SETITEMATTR,
MPFROM2SHORT( wItem1, TRUE ),
MPFROM2SHORT( MIA_CHECKED, 0 ) ) ;
if( wItem2 != 0 )
WinSendMsg( hMenu,
MM_SETITEMATTR,
MPFROM2SHORT( wItem2, TRUE ),
MPFROM2SHORT( MIA_CHECKED, MIA_CHECKED ) ) ;
}
BOOL QueryIni( HAB hab )
/*
** Query INI file
*/
{
BOOL bPos, bData ;
ULONG ulOpts[4] ;
HINI hini ;
ULONG ulCB ;
char *p ;
// get default printer name
PrfQueryProfileString( HINI_PROFILE,
"PM_SPOOLER",
"PRINTER",
";",
achPrinterName,
(long) sizeof achPrinterName ) ;
if( (p=strchr( achPrinterName, ';' )) != NULL ) *p = '\0' ;
// read gnuplot ini file
hini = PrfOpenProfile( hab, GNUINI ) ;
ulCB = sizeof( ulShellPos ) ;
bPos = PrfQueryProfileData( hini, APP_NAME, INISHELLPOS, &ulShellPos, &ulCB ) ;
ulCB = sizeof( ulOpts ) ;
bData = PrfQueryProfileData( hini, APP_NAME, INIOPTS, &ulOpts, &ulCB ) ;
if( bData ) {
bLineTypes = (BOOL)ulOpts[0] ;
bLineThick = (BOOL)ulOpts[1] ;
bColours = (BOOL)ulOpts[2] ;
ulPauseMode = ulOpts[3] ;
}
else {
bLineTypes = FALSE ; /* default values */
bLineThick = FALSE ;
bColours = TRUE ;
ulPauseMode = 1 ;
}
PrfQueryProfileString( hini, APP_NAME, INIFONT, INITIAL_FONT,
szFontNameSize, FONTBUF ) ;
PrfCloseProfile( hini ) ;
bShellPos = bPos ;
return bPos ;
}
static void SaveIni( )
/*
** save data in ini file
*/
{
SWP swp ;
HINI hini ;
ULONG ulOpts[4] ;
hini = PrfOpenProfile( hab, GNUINI ) ;
WinQueryWindowPos( hwndFrame, &swp ) ;
ulPlotPos[0] = swp.x ;
ulPlotPos[1] = swp.y ;
ulPlotPos[2] = swp.cx ;
ulPlotPos[3] = swp.cy ;
PrfWriteProfileData( hini, APP_NAME, INISHELLPOS, &ulPlotPos, sizeof(ulPlotPos) ) ;
/*
WinQueryWindowPos( swGnu.hwnd, &swp ) ;
ulPlotPos[0] = swp.x ;
ulPlotPos[1] = swp.y ;
ulPlotPos[2] = swp.cx ;
ulPlotPos[3] = swp.cy ;
PrfWriteProfileData( hini, APP_NAME, INIPLOTPOS, &ulPlotPos, sizeof(ulPlotPos) ) ;
*/
ulOpts[0] = (ULONG)bLineTypes ;
ulOpts[1] = (ULONG)bLineThick ;
ulOpts[2] = (ULONG)bColours ;
ulOpts[3] = ulPauseMode ;
PrfWriteProfileData( hini, APP_NAME, INIOPTS, &ulOpts, sizeof(ulOpts) ) ;
PrfWriteProfileString( hini, APP_NAME, INIFONT, szFontNameSize ) ;
PrfCloseProfile( hini ) ;
}
static void DoPaint( HWND hWnd, HPS hps )
/*
** Paint the screen with current data
*/
{
RECTL rectClient ;
ULONG ulCount ;
bStopDraw = TRUE ; // stop any drawing in progress and wait for
// thread to signal completion
DosWaitEventSem( semDrawDone, SEM_INDEFINITE_WAIT ) ;
DosResetEventSem( semDrawDone, &ulCount ) ;
WinBeginPaint( hWnd , hps, NULL ) ;
DosPostEventSem( semStartDraw ) ; // start drawing
}
static void ThreadDraw( )
/*
** Thread to draw plot
*/
{
HAB hab ;
RECTL rectClient ;
ULONG ulCount ;
/* initialize and wait until ready to draw */
hab = WinInitialize( 0 ) ;
/* ok - draw until window is destroyed */
while( bExist ) {
// indicate access to window
DosWaitEventSem( semStartDraw, SEM_INDEFINITE_WAIT ) ;
DosResetEventSem( semStartDraw, &ulCount ) ;
// will be set TRUE if we decide to stop in the middle, but now
bStopDraw = FALSE ;
GpiResetPS( hpsScreen, GRES_ALL ) ;
WinQueryWindowRect( hApp, (PRECTL)&rectClient ) ;
GpiSetPageViewport( hpsScreen, &rectClient ) ;
WinFillRect( hpsScreen, &rectClient, CLR_WHITE ) ;
ScalePS( hpsScreen, &rectClient, 0 ) ;
PlotThings( hpsScreen, 0L ) ;
// ok, say that we did it
WinEndPaint( hpsScreen ) ;
DosPostEventSem( semDrawDone ) ;
}
WinTerminate( hab ) ;
}
enum JUSTIFY { LEFT, CENTRE, RIGHT } jmode;
void PlotThings( HPS hps, long lColour )
/*
** Plot a spectrum and related graphs on the designated presentation space
**
** Input:
** HPS hps -- presentation space handle of plot ps
** long lColour -- number of physical colours, used mainly by
** printer drivers to set black & white mode.
** If 0, assume screen display
**
** Note: use semaphore to prevent access to command list while
** pipe thread is reallocating the list.
*/
{
int i, lt, ta, col, sl, n, x, y, cx, cy, width ;
int icnow ;
int cmd ;
char *str, *buf ;
long sw ;
POINTL ptl ;
POINTL aptl[4] ;
FONTMETRICS fm ;
HDC hdc ;
long lVOffset ;
long yDeviceRes ;
long lCurCol ;
long lOldLine = 0 ;
BOOL bBW ;
GRADIENTL grdl ;
BOOL bHorz = TRUE ;
SIZEF sizHor, sizVer ;
/* sometime, make these user modifiable... */
static long lLineTypes[7] = { LINETYPE_SOLID,
LINETYPE_SHORTDASH,
LINETYPE_DOT,
LINETYPE_DASHDOT,
LINETYPE_LONGDASH,
LINETYPE_DOUBLEDOT,
LINETYPE_DASHDOUBLEDOT } ;
static long lCols[15] = { CLR_BLACK,
CLR_DARKGRAY,
CLR_BLUE,
CLR_RED,
CLR_GREEN,
CLR_CYAN,
CLR_PINK,
CLR_YELLOW,
CLR_DARKBLUE,
CLR_DARKRED,
CLR_DARKGREEN,
CLR_DARKCYAN,
CLR_DARKPINK,
CLR_BROWN,
CLR_PALEGRAY } ;
if( commands == NULL ) return ;
/* check for colourless devices */
if( lColour== 1 || lColour == 2 ) bBW = TRUE ;
else bBW = FALSE ;
/* get vertical offset for horizontal text strings */
/* (0.5 em height, so string in vertically centered
about plot position */
GpiQueryFontMetrics( hps, sizeof( FONTMETRICS ), &fm ) ;
lVOffset = fm.lEmHeight ;
/* loop over accumulated commands from inboard driver */
DosRequestMutexSem( semCommands, SEM_INDEFINITE_WAIT ) ;
GpiSetLineWidth( hps, bLineThick?LINEWIDTH_THICK:LINEWIDTH_NORMAL ) ;
for( i=0; bExist && i<ic; ) {
if( bStopDraw ) break ;
cmd = commands[i++];
/* PM_vector(x,y) - draw vector */
if (cmd == 'V') {
ptl.x = (LONG)commands[i++] ; ptl.y = (LONG)commands[i++] ;
GpiLine( hps, &ptl ) ;
}
/* PM_move(x,y) - move */
else if (cmd == 'M') {
ptl.x = (LONG)commands[i++] ; ptl.y = (LONG)commands[i++] ;
GpiMove( hps, &ptl ) ;
}
/* PM_put_text(x,y,str) - draw text */
else if (cmd == 'T') {
x = commands[i++] ;
y = commands[i++] ;
str = (char*)&commands[i] ;
sl = strlen(str) ;
i += 1+sl/sizeof(int) ;
lCurCol = GpiQueryColor( hps ) ;
GpiSetColor( hps, CLR_BLACK ) ;
GpiQueryTextBox( hps, (LONG)strlen( str ), str, 4L, aptl ) ;
if( bHorz ) sw = aptl[3].x ;
else sw = aptl[3].y ;
switch(jmode) {
case LEFT: sw = 0; break;
case CENTRE: sw = -sw/2; break;
case RIGHT: sw = -sw; break;
}
if( bHorz ) {
ptl.x = (LONG)(x+sw) ; ptl.y = (LONG)(y-lVOffset/4) ;
}
else {
ptl.x = (LONG)x ; ptl.y = (LONG)(y+sw) ;
}
GpiCharStringAt( hps, &ptl, (LONG) strlen( str ) , str ) ;
GpiSetColor( hps, lCurCol ) ;
}
/* PM_justify_text(mode) - set text justification mode */
else if (cmd == 'J')
jmode = commands[i++] ;
/* PM_linetype(type) - set line type */
/* mapped to colour */
else if (cmd == 'L') {
lt = commands[i++] ;
/* linetype = -2 axes, -1 border, 0 arrows, all to 0 */
col = lt ;
if( lt == -1 ) GpiSetLineWidth( hps, LINEWIDTH_NORMAL ) ;
else GpiSetLineWidth( hps, bLineThick?LINEWIDTH_THICK:LINEWIDTH_NORMAL ) ;
if( lt < 0 ) lt = 0 ;
lt = (lt%8);
col = (col+2)%16 ;
if( bLineTypes || bBW ) {
GpiSetLineType( hps, lLineTypes[lt] ) ;
}
if( !bBW ) /* maintain some flexibility here in case we don't want
the model T option */
if( bColours ) GpiSetColor( hps, lCols[col] ) ;
else GpiSetColor( hps, CLR_BLACK ) ;
}
else if (cmd == 'D') { /* point/dot mode - may need colour change */
lt = commands[i++] ; /* 1: enter point mode, 0: exit */
if( bLineTypes || bBW ) {
if( lt == 1 ) lOldLine = GpiSetLineType( hps, lLineTypes[0] ) ;
else GpiSetLineType( hps, lOldLine ) ;
}
}
/* PM_text_angle(ang) - set text angle, 0 horz, 1 vert */
else if (cmd == 'A') {
ta = commands[i++] ;
if( ta == 0 ) {
grdl.x = 0L ; grdl.y = 0L ;
GpiSetCharAngle( hps, &grdl ) ;
if( !bHorz ) {
GpiQueryCharBox( hps, &sizVer ) ;
sizHor.cx = sizVer.cy ; sizHor.cy = sizVer.cx ;
GpiSetCharBox( hps, &sizHor ) ;
bHorz = TRUE ;
}
}
else if( ta == 1 ) {
grdl.x = 0L ; grdl.y = 1L ;
GpiSetCharAngle( hps, &grdl ) ;
if( bHorz ) {
GpiQueryCharBox( hps, &sizHor ) ;
sizVer.cx = sizHor.cy ; sizVer.cy = sizHor.cx ;
GpiSetCharBox( hps, &sizVer ) ;
bHorz = FALSE ;
}
}
else continue ;
}
}
DosReleaseMutexSem( semCommands ) ;
}
short ScalePS( HPS hps, PRECTL prect, USHORT usFlags )
/*
** Get a font to use
** Scale the plot area to world coords for subsequent plotting
*/
{
RECTL rectView, rectClient ;
SIZEL sizePage ;
static char *szFontName ;
static short shFontSize ;
rectClient = *prect ;
sizePage.cx = GNUPAGE ;
sizePage.cy = GNUPAGE ;
sscanf( szFontNameSize, "%d", &shFontSize ) ;
szFontName = strchr( szFontNameSize, '.' ) + 1 ;
rectView.xLeft = 0L ;
rectView.xRight = sizePage.cx ;
rectView.yBottom = 0L ; rectView.yTop = sizePage.cy ;
GpiSetPS( hps, &sizePage, PU_ARBITRARY ) ;
GpiSetPageViewport( hps, &rectClient ) ;
SelectFont( hps, szFontName, shFontSize ) ;
GpiSetGraphicsField( hps, &rectView ) ;
return 0 ;
}
void SelectFont( HPS hps, char *szFont, short shPointSize )
/*
** Select a named and sized outline (adobe) font
*/
{
HDC hdc ;
static FATTRS fat ;
LONG xDeviceRes, yDeviceRes ;
POINTL ptlFont ;
SIZEF sizfx ;
static LONG lcid = 0L ;
fat.usRecordLength = sizeof fat ;
fat.fsSelection = 0 ;
fat.lMatch = 0 ;
fat.idRegistry = 0 ;
fat.usCodePage = GpiQueryCp (hps) ;
fat.lMaxBaselineExt = 0 ;
fat.lAveCharWidth = 0 ;
fat.fsType = 0 ;
fat.fsFontUse = FATTR_FONTUSE_OUTLINE |
FATTR_FONTUSE_TRANSFORMABLE ;
strcpy (fat.szFacename, szFont) ;
if( lcid == 0L ) lcid = 1L ;
else {
GpiSetCharSet( hps, 0L) ;
GpiDeleteSetId( hps, lcid ) ;
}
GpiCreateLogFont (hps, NULL, lcid, &fat) ;
GpiSetCharSet( hps, lcid ) ;
hdc = GpiQueryDevice (hps) ;
DevQueryCaps (hdc, CAPS_HORIZONTAL_RESOLUTION, 1L, &xDeviceRes) ;
DevQueryCaps (hdc, CAPS_VERTICAL_RESOLUTION, 1L, &yDeviceRes) ;
// Find desired font size in pixels
ptlFont.x = 254L * (long)shPointSize * xDeviceRes / 720000L ;
ptlFont.y = 254L * (long)shPointSize * yDeviceRes / 720000L ;
// Convert to page units
GpiConvert (hps, CVTC_DEVICE, CVTC_PAGE, 1L, &ptlFont) ;
// Set the character box
sizfx.cx = MAKEFIXED (ptlFont.x, 0) ;
sizfx.cy = MAKEFIXED (ptlFont.y, 0) ;
GpiSetCharBox (hps, &sizfx) ;
}
static void ReadGnu()
/*
** Thread to read plot commands from GNUPLOT pm driver.
** Opens named pipe, then clears semaphore to allow GNUPLOT driver to proceed.
** Reads commands and builds a command list.
*/
{
char *szEnv ;
char *szFileBuf ;
ULONG rc;
USHORT usErr ;
ULONG cbR ;
STARTDATA start ;
USHORT i ;
PID ppid ;
unsigned char buff[2] ;
int len ;
HEV hev ;
static char *szPauseText = NULL ;
ULONG ulPause ;
char *pszPipeName, *pszSemName ;
#ifdef USEOWNALLOC
DosAllocMem( &commands, 64*1024*1024, PAG_READ|PAG_WRITE ) ;
#endif
DosEnterCritSec() ;
pszPipeName = malloc( 256 ) ;
pszSemName = malloc( 256 ) ;
DosExitCritSec() ;
strcpy( pszPipeName, "\\pipe\\" ) ;
strcpy( pszSemName, "\\sem32\\" ) ;
strcat( pszPipeName, szIPCName ) ;
strcat( pszSemName, szIPCName ) ;
/* open a named pipe for communication with gnuplot */
rc = DosCreateNPipe( pszPipeName,
&hRead,
NP_ACCESS_DUPLEX|NP_NOINHERIT|NP_NOWRITEBEHIND ,
1|NP_WAIT|NP_READMODE_MESSAGE|NP_TYPE_MESSAGE,
PIPEBUF,
PIPEBUF,
0xFFFFFFFF) ;
hev = 0 ; /* OK, gnuplot can try to open npipe ... */
DosOpenEventSem( pszSemName, &hev ) ;
DosPostEventSem( hev ) ;
/* attach to gnuplot */
if( DosConnectNPipe( hRead ) == 0L ) {
/* store graphics commands */
/* use semaphore to prevent problems with drawing while reallocating
the command buffers */
DosRead( hRead, &ppidGnu, 4, &cbR ) ;
DosPostEventSem( semStartSeq ) ; /* once we've got pidGnu */
while (1) {
usErr=BufRead(hRead,buff, 1, &cbR) ;
if( usErr != 0 ) break ;
switch( *buff ) {
case 'G' : /* enter graphics mode */
/* wait for access to command list and lock it */
DosRequestMutexSem( semCommands, SEM_INDEFINITE_WAIT ) ;
DosEnterCritSec() ;
#ifdef USEOWNALLOC
if( ncalloc > 0 ) {
DosSetMem( commands, ncalloc*sizeof(int), PAG_DECOMMIT ) ;
#else
if (commands!=NULL) { // delete all old commands and prepare for new
free(commands);
#endif
}
ic = 0 ;
ncalloc = CMDALLOC ;
#ifdef USEOWNALLOC
DosSetMem( commands, ncalloc*sizeof(int), PAG_COMMIT|PAG_DEFAULT ) ;
#else
commands = (int*)malloc(ncalloc*sizeof(int)) ;
#endif
DosExitCritSec() ;
DosReleaseMutexSem( semCommands ) ;
break ;
case 'E' : /* leave graphics mode (graph completed) */
Display() ; /* plot graph */
break ;
case 'R' :
/* gnuplot has reset drivers, we do nothing */
break ;
case 'M' : /* move */
case 'V' : /* draw vector */
commands[ ic++ ] = (int)*buff ;
if( ic+2 >= ncalloc ) AllocMore() ;
BufRead(hRead,&commands[ic], 2*sizeof(int), &cbR) ;
ic+=2 ;
break ;
case 'P' : /* pause */
BufRead(hRead,&len, sizeof(int), &cbR) ;
len = (len+sizeof(int)-1)/sizeof(int) ;
if( len > 0 ){ /* get pause text */
szPauseText = malloc( len*sizeof(int) ) ;
BufRead(hRead,szPauseText, len*sizeof(int), &cbR) ;
}
if( ulPauseMode != PAUSE_GNU ) {
/* pause and wait for semaphore to be cleared */
DosResetEventSem( semPause, &ulPause ) ;
WinPostMsg( hApp, WM_PAUSEPLOT, (MPARAM) szPauseText, 0L ) ;
DosWaitEventSem( semPause, SEM_INDEFINITE_WAIT ) ;
}
else { /* gnuplot handles pause */
ulPauseReply = 2 ;
}
if( szPauseText != NULL ) free( szPauseText ) ;
szPauseText = NULL ;
/* reply to gnuplot so it can continue */
DosWrite( hRead, &ulPauseReply, sizeof(int), &cbR ) ;
break ;
case 'T' : /* write text */
commands[ ic++ ] = (int)*buff ;
if( ic+1 >= ncalloc ) AllocMore() ;
/* read x, y, len */
BufRead(hRead,&commands[ic++], sizeof(int), &cbR) ;
BufRead(hRead,&commands[ic++], sizeof(int), &cbR) ;
BufRead(hRead,&len, sizeof(int), &cbR) ;
if( ic+1+((len+sizeof(int)-1)/sizeof(int)) >= ncalloc ) AllocMore() ;
BufRead(hRead,&commands[ic], len, &cbR) ;
if( len == 0 ) len = 1 ;
ic += (len+sizeof(int)-1)/sizeof(int) ;
break ;
case 'J' : /* justify */
case 'A' : /* text angle */
case 'L' : /* line type */
case 'D' : /* points mode */
commands[ ic++ ] = (int)*buff ;
if( ic+1 >= ncalloc ) AllocMore() ;
BufRead(hRead,&commands[ic++], sizeof(int), &cbR) ;
break ;
default : /* should handle error */
break ;
}
}
}
DosEnterCritSec() ;
free( szFileBuf ) ;
free( szEnv ) ;
DosExitCritSec() ;
pidGnu = 0 ; /* gnuplot has shut down (?) */
WinPostMsg( hApp, WM_CLOSE, 0L, 0L ) ;
}
static int BufRead( HFILE hfile, void *buf, int nBytes, ULONG *pcbR )
/*
** pull next plot command out of buffer read from GNUPLOT
*/
{
ULONG ulR, ulRR ;
static char buffer[GNUBUF] ;
static char *pbuffer = buffer+GNUBUF, *ebuffer = buffer+GNUBUF ;
for( ; nBytes > 0 ; nBytes-- ) {
if( pbuffer >= ebuffer ) {
ulR = GNUBUF ;
DosRead( hfile, buffer, ulR, &ulRR ) ;
pbuffer = buffer ;
ebuffer = pbuffer+ulRR ;
}
*(char*)buf++ = *pbuffer++ ;
}
return 0L ;
}
static void AllocMore()
/*
** Allocate more memory for plot commands
*/
{
DosRequestMutexSem( semCommands, SEM_INDEFINITE_WAIT ) ;
DosEnterCritSec() ;
#ifdef USEOWNALLOC
DosSetMem( commands+ncalloc, CMDALLOC*sizeof(int), PAG_COMMIT|PAG_DEFAULT ) ;
#endif
ncalloc = ncalloc + CMDALLOC ;
#ifndef USEOWNALLOC
commands = (int*)realloc(commands, ncalloc*sizeof(int)) ;
#endif
DosExitCritSec() ;
DosReleaseMutexSem( semCommands ) ;
}
static void Display()
/*
** Display gnuplot results
** -- must post message as this thread is not drawing thread
*/
{
WinPostMsg( hApp, WM_GNUPLOT, 0L, 0L ) ;
}
int GetNewFont( HWND hwnd, HPS hps )
/*
** Get a new font using standard font dialog
*/
{
static FONTDLG pfdFontdlg; /* Font dialog info structure */
static int i1 =1 ;
static int iSize ;
char szPtList[64] ;
HWND hwndFontDlg; /* Font dialog window handle */
char *p ;
char szFamilyname[FACESIZE];
if( i1 ) {
strcpy( pfdFontdlg.fAttrs.szFacename, strchr( szFontNameSize, '.' ) + 1 ) ;
strcpy( szFamilyname, strchr( szFontNameSize, '.' ) + 1 ) ;
sscanf( szFontNameSize, "%d", &iSize ) ;
memset(&pfdFontdlg, 0, sizeof(FONTDLG));
pfdFontdlg.cbSize = sizeof(FONTDLG);
pfdFontdlg.hpsScreen = hps;
/* szFamilyname[0] = 0;*/
pfdFontdlg.pszFamilyname = szFamilyname;
pfdFontdlg.usFamilyBufLen = FACESIZE;
pfdFontdlg.fl = FNTS_HELPBUTTON | FNTS_CENTER | FNTS_VECTORONLY | FNTS_INITFROMFATTRS ;
pfdFontdlg.clrFore = CLR_BLACK;
pfdFontdlg.clrBack = CLR_WHITE;
pfdFontdlg.usWeight = 5 ;
pfdFontdlg.fAttrs.usCodePage = 0;
i1=0;
}
sprintf( szPtList, "%d 8 10 12 14 18 24", iSize ) ;
pfdFontdlg.pszPtSizeList = szPtList ;
pfdFontdlg.fxPointSize = MAKEFIXED(iSize,0);
hwndFontDlg = WinFontDlg(HWND_DESKTOP, hwnd, &pfdFontdlg);
if (hwndFontDlg && (pfdFontdlg.lReturn == DID_OK)) {
iSize = FIXEDINT( pfdFontdlg.fxPointSize ) ;
sprintf( szFontNameSize, "%d.%s", iSize, pfdFontdlg.fAttrs.szFacename ) ;
return 1 ;
}
else return 0 ;
}